import { http } from "@/utils/http";
import type { ApiResponse } from "../user";
import { ensureArray, normalisePagination, toNumber } from "@/api/_helpers";

const ROLE_BASE = "/system/role";

export interface RoleListParams {
  page?: number;
  page_size?: number;
  name?: string;
  code?: string;
  status?: number | string;
  keyword?: string;
  scope_type?: string;
}

export interface RoleItem {
  id: number;
  name: string;
  code: string;
  slug: string;
  status: number;
  description?: string | null;
  created_at?: string | null;
  updated_at?: string | null;
  permissions?: Array<string>;
  permission_ids?: Array<number>;
  [key: string]: any;
}

export interface RolePermissionsSelection {
  ids: Array<number>;
  codes: Array<string>;
}

export interface RoleListResult {
  list: Array<RoleItem>;
  total: number;
  pageSize: number;
  currentPage: number;
  raw?: any;
}

export interface RolePayload {
  name: string;
  slug: string;
  status?: number;
  description?: string | null;
  scope_type?: string;
  permission_ids?: Array<number>;
}

const mapRole = (item: Record<string, any>): RoleItem => {
  const permissionSource = ensureArray<any>(
    item.permissions ?? item.perms ?? []
  );
  const permissionCodes = permissionSource
    .map(permission => {
      if (typeof permission === "string" || typeof permission === "number") {
        return String(permission);
      }
      return (
        permission?.code ?? permission?.slug ?? String(permission?.id ?? "")
      );
    })
    .filter(code => Boolean(code)) as Array<string>;

  const permissionIds = permissionSource
    .map(permission => {
      if (typeof permission === "number") return toNumber(permission, 0);
      if (typeof permission === "string") return NaN;
      return toNumber(permission?.id ?? permission?.permission_id, 0);
    })
    .filter(id => Number.isFinite(id) && id > 0) as Array<number>;

  return {
    id: toNumber(item.id, 0),
    name: item.name ?? "",
    code: item.slug ?? item.code ?? "",
    slug: item.slug ?? item.code ?? "",
    status: toNumber(item.status, 0),
    description: item.description ?? item.remark ?? "",
    created_at: item.create_time ?? item.created_at ?? "",
    updated_at: item.update_time ?? item.updated_at ?? "",
    permissions: permissionCodes,
    permission_ids: permissionIds
  };
};

const fetchList = async (
  params: RoleListParams = {}
): Promise<RoleListResult> => {
  const page = toNumber(params.page, 1);
  const pageSize = toNumber(params.page_size, 10);
  const response = await http.request<ApiResponse<any>>("get", ROLE_BASE, {
    params: {
      ...params,
      page,
      page_size: pageSize
    }
  });
  const payload = (response?.data as Record<string, any>) ?? {};
  const listSource =
    payload.list ?? payload.data ?? payload.records ?? payload.items ?? [];
  const list = ensureArray<Record<string, any>>(listSource).map(mapRole);
  const pagination = normalisePagination(
    payload.pagination ?? payload,
    page,
    pageSize,
    list.length
  );
  return {
    list,
    total: pagination.total,
    pageSize: pagination.pageSize,
    currentPage: pagination.currentPage,
    raw: payload
  };
};

const create = async (payload: RolePayload): Promise<RoleItem> => {
  const res = await http.request<ApiResponse<any>>("post", ROLE_BASE, {
    data: {
      name: payload.name,
      slug: payload.slug,
      description: payload.description ?? null,
      status: payload.status ?? 1,
      scope_type: payload.scope_type ?? "system",
      permission_ids: payload.permission_ids ?? []
    }
  });
  const data = (res?.data as Record<string, any>) ?? {};
  return mapRole(data);
};

const update = async (id: number, payload: RolePayload): Promise<RoleItem> => {
  const res = await http.request<ApiResponse<any>>(
    "put",
    `${ROLE_BASE}/${id}`,
    {
      data: {
        name: payload.name,
        slug: payload.slug,
        description: payload.description ?? null,
        status: payload.status ?? 1,
        scope_type: payload.scope_type ?? "system",
        permission_ids: payload.permission_ids
      }
    }
  );
  const data = (res?.data as Record<string, any>) ?? {};
  return mapRole(data);
};

const remove = async (id: number): Promise<boolean> => {
  const res = await http.request<ApiResponse<any>>(
    "delete",
    `${ROLE_BASE}/${id}`
  );
  if (typeof res?.data === "boolean") return res.data;
  if (res?.success !== undefined) return Boolean(res.success);
  return true;
};

const fetchPermissions = async (
  id: number
): Promise<RolePermissionsSelection> => {
  const res = await http.request<ApiResponse<any>>("get", `${ROLE_BASE}/${id}`);
  const payload = (res?.data as Record<string, any>) ?? {};
  const source = ensureArray<any>(
    payload.permissions ?? payload.perms ?? payload
  );

  const codes = source
    .map((item: any) => {
      if (typeof item === "string" || typeof item === "number") {
        return String(item);
      }
      return item?.code ?? item?.slug ?? String(item?.id ?? "");
    })
    .filter(code => Boolean(code)) as Array<string>;

  const ids = source
    .map((item: any) => {
      if (typeof item === "number") return toNumber(item, 0);
      if (typeof item === "string") return NaN;
      return toNumber(item?.id ?? item?.permission_id, 0);
    })
    .filter(id => Number.isFinite(id) && id > 0) as Array<number>;

  return {
    ids,
    codes
  };
};

const savePermissions = async (
  id: number,
  permissionIds: Array<number>
): Promise<RoleItem> => {
  const res = await http.request<ApiResponse<any>>(
    "put",
    `${ROLE_BASE}/${id}`,
    {
      data: { permission_ids: permissionIds }
    }
  );
  const data = (res?.data as Record<string, any>) ?? {};
  return mapRole(data);
};

export default {
  fetchList,
  create,
  update,
  remove,
  fetchPermissions,
  savePermissions
};
